package mysqlgo

import (
	"fmt"
	"strings"
)

var (
	selectSQL = "SELECT%DISTINCT% %FIELD% FROM %TABLE%%JOIN%%WHERE%%GROUP%%HAVING%%ORDER%%LIMIT% %UNION%%COMMENT%"
	insertSQL = "INSERT INTO %TABLE%(%FIELD%) VALUE(%MARK%)"
	updateSQL = "UPDATE %TABLE% SET %FIELD% WHERE %ARGS%"
	deleteSQL = "DELETE FORM %TABLE% WHERE %AGRS%"
)

//SQLBuilder SQL生成工具类
type SQLBuilder struct {
	lastSQL			string
	PreviewSQL		bool
}

var exp = map[string]string {
	"EQ"		: "==",
	"NEQ" 		: "<>",
	"GT"		: ">",
	"NGT"		: ">=",
	"LT"		: "<",
	"ELT"		: "<=",
	"NLIKE"		: "NOT LIKE",
	"LIKE"		: "LIKE",
	"IN"		: "IN",
	"NOTIN"		: "NOT IN",
	"BETWEEN"	: "BETWEEN",
	"NBETWEEN"	: "NOT BETWEEN",
}

//SQLTYPE SQL类型
type SQLTYPE int

const (
	query 	SQLTYPE = 0		//查询
	insert 	SQLTYPE = 1		//插入
	update 	SQLTYPE = 2		//更新
	delete	SQLTYPE = 3		//删除
)

//LastSQL 最后一次执行后生成的SQL语句
func (builder *SQLBuilder) LastSQL() string {
	return builder.lastSQL
}

//BuildSQL 构造SQL
func (builder *SQLBuilder) BuildSQL(t SQLTYPE, options *option, data map[string]interface{}) string {
	switch t {
	case query:
		fmt.Println(options)
		builder.lastSQL = builder.parseQuerySQL(options)
		break
	case insert:
		builder.lastSQL = builder.parseInsertSQL(options)
		break
	case update:
		builder.lastSQL = builder.parseUpdateSQL(options, data)
		break
	case delete:
		builder.lastSQL = builder.parseDeleteSQL(options)
		break
	}
	builder.printSQL()
	return builder.lastSQL
}

func (builder *SQLBuilder) printSQL() {
	if builder.PreviewSQL {
		fmt.Printf("[SQLBuilder Preview]: %s \n", builder.lastSQL)
	}
}

func (builder *SQLBuilder) parseQuerySQL(options *option) string {
	var sql = selectSQL
	sql = strings.Replace(sql, "%TABLE%", options.parseTable(), -1)
	sql = strings.Replace(sql, "%DISTINCT%", options.parseDistinct(), -1)
	sql = strings.Replace(sql, "%FIELD%", options.parseField(), -1)
	sql = strings.Replace(sql, "%JOIN%", options.parseJoin(), -1)
	sql = strings.Replace(sql, "%WHERE%", options.parseWhere(), -1)
	sql = strings.Replace(sql, "%GROUP%", options.parseGroup(), -1)
	sql = strings.Replace(sql, "%HAVING%", options.parseHaving(), -1)
	sql = strings.Replace(sql, "%ORDER%", options.parseOrder(), -1)
	sql = strings.Replace(sql, "%LIMIT%", options.parseLimit(), -1)
	sql = strings.Replace(sql, "%UNION%", options.parseUnion(), -1)
	sql = strings.Replace(sql, "%COMMENT%", options.parseComment(), -1)
	return sql
}

func (builder *SQLBuilder) parseInsertSQL(options *option) string {
	var sql = insertSQL
	sql = strings.Replace(sql, "%TABLE%", options.parseTable(), -1)
	sql = strings.Replace(sql, "%FIELD%", options.parseField(), -1)
	sql = strings.Replace(sql, "%MARK%", options.parseFiledMark(), -1)
	return sql
}

func (builder *SQLBuilder) parseUpdateSQL(options *option, data map[string]interface{}) string {
	var sql = updateSQL
	sql = strings.Replace(sql,  "%TABLE%", options.parseTable(), -1)
	var keys []string
	var values []interface{}
	for key , value := range data {
		keys = append(keys, fmt.Sprintf("%s = ?" , key))
		values = append(values, value)
	}
	sql = strings.Replace(sql, "%FIELD%", strings.Join(keys, ","), -1)
	sql = strings.Replace(sql, "%ARGS%", options.parseWhere(), -1)
	options.setArgs(values...)
	return sql
}

func (builder *SQLBuilder) parseDeleteSQL(options *option) string {
	var sql = deleteSQL
	sql = strings.Replace(sql, "%TABLE%", options.parseTable(), -1)
	if len(options.whereArgs) > 0 {
		panic("[SQLBuilder parseDeleteSQL]: The condition is NULL")
	}
	sql = strings.Replace(sql, "%ARGS%", options.parseWhere(), -1)
	return sql
}